home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / UsingPDF / GhostScript / source / gs5.10 / zgstate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-26  |  10.9 KB  |  454 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* zgstate.c */
  20. /* Graphics state operators */
  21. #include "math_.h"
  22. #include "ghost.h"
  23. #include "errors.h"
  24. #include "oper.h"
  25. #include "ialloc.h"
  26. #include "idict.h"
  27. #include "istruct.h"
  28. #include "igstate.h"
  29. #include "gsmatrix.h"
  30. #include "store.h"
  31.  
  32. /* Forward references */
  33. private int near num_param(P2(const_os_ptr, int (*)(P2(gs_state *, floatp))));
  34.  
  35. /* Structure descriptors */
  36. private_st_int_gstate();
  37.  
  38. /* ------ Operations on the entire graphics state ------ */
  39.  
  40. /* The current graphics state */
  41. gs_state *igs;
  42. private gs_gc_root_t igs_root;
  43.  
  44. /* An empty dictionary for the pagedevice member of the int_gstate. */
  45. ref i_null_pagedevice;
  46. private ref *npd_p;
  47. private gs_gc_root_t npd_root;
  48.  
  49. /* "Client" procedures */
  50. private void *gs_istate_alloc(P1(gs_memory_t *mem));
  51. private int gs_istate_copy(P2(void *to, const void *from));
  52. private void gs_istate_free(P2(void *old, gs_memory_t *mem));
  53. private const gs_state_client_procs istate_procs = {
  54.     gs_istate_alloc,
  55.     gs_istate_copy,
  56.     gs_istate_free
  57. };
  58.  
  59. /* Initialize the graphics stack. */
  60. #ifdef DPNEXT
  61. void
  62. igs_init(void)
  63. {    dict_create(0, &i_null_pagedevice);
  64.     r_clear_attrs(&i_null_pagedevice, a_write);
  65.     npd_p = &i_null_pagedevice;
  66.     gs_register_ref_root(imemory, &npd_root, (void **)&npd_p, "igs(npd)");
  67.     gs_register_struct_root(imemory, &igs_root, (void **)&igs, "igs");
  68.     igs = int_gstate_alloc(iimemory);
  69. }
  70. gs_state *
  71. int_gstate_alloc(gs_ref_memory_t *mem)
  72. {
  73. #else
  74. void
  75. igs_init(void)
  76. {
  77. #endif
  78.     int_gstate *iigs;
  79.     ref proc0;
  80.  
  81. #ifdef DPNEXT
  82.     gs_state *pgs = gs_state_alloc((gs_memory_t *)mem);
  83.  
  84.     iigs = gs_alloc_struct((gs_memory_t *)mem, int_gstate, &st_int_gstate,
  85.                    "int_gstate_alloc(int_gstate)");
  86. #else
  87.     igs = gs_state_alloc(imemory);
  88.     iigs = gs_alloc_struct(imemory, int_gstate, &st_int_gstate,
  89.                    "igs_init");
  90. #endif
  91.     int_gstate_map_refs(iigs, make_null);
  92.     make_empty_array(&iigs->dash_pattern, a_all);
  93. #ifdef DPNEXT
  94.     gs_alloc_ref_array(mem, &proc0, a_readonly + a_executable, 2,
  95.                "int_gstate_alloc(proc0)");
  96. #else
  97.     ialloc_ref_array(&proc0, a_readonly + a_executable, 2,
  98.              "igs_init");
  99. #endif
  100.     make_oper(proc0.value.refs, 0, zpop);
  101.     make_real(proc0.value.refs + 1, 0.0);
  102.     iigs->black_generation = proc0;
  103.     iigs->undercolor_removal = proc0;
  104. #ifndef DPNEXT
  105.     dict_create(0, &i_null_pagedevice);
  106.     r_clear_attrs(&i_null_pagedevice, a_write);
  107. #endif
  108.     iigs->pagedevice = i_null_pagedevice;
  109. #ifdef DPNEXT
  110.     gs_state_set_client(pgs, iigs, &istate_procs);
  111.     /* PostScript code wants limit clamping enabled. */
  112.     gs_setlimitclamp(pgs, true);
  113. #else
  114.     npd_p = &i_null_pagedevice;
  115.     gs_register_ref_root(imemory, &npd_root, (void **)&npd_p, "igs(npd)");
  116.     gs_state_set_client(igs, iigs, &istate_procs);
  117.     gs_register_struct_root(imemory, &igs_root, (void **)&igs, "igs");
  118.     /* PostScript code wants limit clamping enabled. */
  119.     gs_setlimitclamp(igs, true);
  120. #endif
  121.     /*
  122.      * gsave and grestore only work properly
  123.      * if there are always at least 2 entries on the stack.
  124.      * We count on the PostScript initialization code to do a gsave.
  125.      */
  126. #ifdef DPNEXT
  127.     return pgs;
  128. #endif
  129. }
  130.  
  131. /* - gsave - */
  132. int
  133. zgsave(register os_ptr op)
  134. {    return gs_gsave(igs);
  135. }
  136.  
  137. /* - grestore - */
  138. int
  139. zgrestore(register os_ptr op)
  140. {    return gs_grestore(igs);
  141. }
  142.  
  143. /* - grestoreall - */
  144. int
  145. zgrestoreall(register os_ptr op)
  146. {    return gs_grestoreall(igs);
  147. }
  148.  
  149. /* - initgraphics - */
  150. private int
  151. zinitgraphics(register os_ptr op)
  152. {    /* gs_initgraphics does a setgray; we must clear the interpreter's */
  153.     /* cached copy of the color space object. */
  154.     int code = gs_initgraphics(igs);
  155.     if ( code >= 0 )
  156.       make_null(&istate->colorspace.array);
  157.     return code;
  158. }
  159.  
  160. /* ------ Operations on graphics state elements ------ */
  161.  
  162. /* <num> setlinewidth - */
  163. private int
  164. zsetlinewidth(register os_ptr op)
  165. {    /*
  166.      * The Red Book doesn't say anything about this, but Adobe
  167.      * interpreters return (or perhaps store) the absolute value
  168.      * of the width.
  169.      */
  170.     double width;
  171.     int code = real_param(op, &width);
  172.  
  173.     if ( code < 0 )
  174.       return_op_typecheck(op);
  175.     code = gs_setlinewidth(igs, fabs(width));
  176.     if ( code >= 0 )
  177.       pop(1);
  178.     return code;
  179. }
  180.  
  181. /* - currentlinewidth <num> */
  182. private int
  183. zcurrentlinewidth(register os_ptr op)
  184. {    push(1);
  185.     make_real(op, gs_currentlinewidth(igs));
  186.     return 0;
  187. }
  188.  
  189. /* <cap_int> .setlinecap - */
  190. private int
  191. zsetlinecap(register os_ptr op)
  192. {    int param;
  193.     int code = int_param(op, max_int, ¶m);
  194.  
  195.     if ( code < 0 || (code = gs_setlinecap(igs, (gs_line_cap)param)) < 0 )
  196.       return code;
  197.     pop(1);
  198.     return 0;
  199. }
  200.  
  201. /* - currentlinecap <cap_int> */
  202. private int
  203. zcurrentlinecap(register os_ptr op)
  204. {    push(1);
  205.     make_int(op, (int)gs_currentlinecap(igs));
  206.     return 0;
  207. }
  208.  
  209. /* <join_int> .setlinejoin - */
  210. private int
  211. zsetlinejoin(register os_ptr op)
  212. {    int param;
  213.     int code = int_param(op, max_int, ¶m);
  214.  
  215.     if ( code < 0 || (code = gs_setlinejoin(igs, (gs_line_join)param)) < 0 )
  216.       return code;
  217.     pop(1);
  218.     return 0;
  219. }
  220.  
  221. /* - currentlinejoin <join_int> */
  222. private int
  223. zcurrentlinejoin(register os_ptr op)
  224. {    push(1);
  225.     make_int(op, (int)gs_currentlinejoin(igs));
  226.     return 0;
  227. }
  228.  
  229. /* <num> setmiterlimit - */
  230. private int
  231. zsetmiterlimit(register os_ptr op)
  232. {    return num_param(op, gs_setmiterlimit);
  233. }
  234.  
  235. /* - currentmiterlimit <num> */
  236. private int
  237. zcurrentmiterlimit(register os_ptr op)
  238. {    push(1);
  239.     make_real(op, gs_currentmiterlimit(igs));
  240.     return 0;
  241. }
  242.  
  243. /* <array> <offset> setdash - */
  244. private int
  245. zsetdash(register os_ptr op)
  246. {    os_ptr op1 = op - 1;
  247.     double offset;
  248.     int code = real_param(op, &offset);
  249.     uint i, n;
  250.     gs_memory_t *mem = imemory;
  251.     float *pattern;
  252.  
  253.     if ( code < 0 )
  254.       return_op_typecheck(op);
  255.     if ( !r_is_array(op1) )
  256.       return_op_typecheck(op1);
  257.     /* Adobe interpreters apparently don't check the array for */
  258.     /* read access, so we won't either. */
  259.     /*check_read(*op1);*/
  260.     /* Unpack the dash pattern and check it */
  261.     n = r_size(op1);
  262.     pattern =
  263.       (float *)gs_alloc_byte_array(mem, n, sizeof(float), "setdash");
  264.     if ( pattern == 0 )
  265.       return_error(e_VMerror);
  266.     for ( i = 0, code = 0; i < n && code >= 0; ++i )
  267.       { ref element;
  268.         array_get(op1, (long)i, &element);
  269.         code = float_param(&element, &pattern[i]);
  270.       }
  271.     if ( code >= 0 )
  272.       code = gs_setdash(igs, pattern, n, offset);
  273.     gs_free_object(mem, pattern, "setdash"); /* gs_setdash copies this */
  274.     if ( code < 0 )
  275.       return code;
  276.     ref_assign(&istate->dash_pattern, op1);
  277.     pop(2);
  278.     return code;
  279. }
  280.  
  281. /* - currentdash <array> <offset> */
  282. private int
  283. zcurrentdash(register os_ptr op)
  284. {    push(2);
  285.     ref_assign(op - 1, &istate->dash_pattern);
  286.     make_real(op, gs_currentdash_offset(igs));
  287.     return 0;
  288. }
  289.  
  290. /* <num> setflat - */
  291. private int
  292. zsetflat(register os_ptr op)
  293. {    return num_param(op, gs_setflat);
  294. }
  295.  
  296. /* - currentflat <num> */
  297. private int
  298. zcurrentflat(register os_ptr op)
  299. {    push(1);
  300.     make_real(op, gs_currentflat(igs));
  301.     return 0;
  302. }
  303.  
  304. /* ------ Extensions ------ */
  305.  
  306. /* <bool> .setaccuratecurves - */
  307. private int
  308. zsetaccuratecurves(register os_ptr op)
  309. {    check_type(*op, t_boolean);
  310.     gs_setaccuratecurves(igs, op->value.boolval);
  311.     pop(1);
  312.     return 0;
  313. }
  314.  
  315. /* - .currentaccuratecurves <bool> */
  316. private int
  317. zcurrentaccuratecurves(register os_ptr op)
  318. {    push(1);
  319.     make_bool(op, gs_currentaccuratecurves(igs));
  320.     return 0;
  321. }
  322.  
  323. /* <adjust.x> <adjust.y> .setfilladjust2 - */
  324. private int
  325. zsetfilladjust2(register os_ptr op)
  326. {    double adjust[2];
  327.     int code = num_params(op, 2, adjust);
  328.  
  329.     if ( code < 0 )
  330.       return code;
  331.     code = gs_setfilladjust(igs, adjust[0], adjust[1]);
  332.     if ( code < 0 )
  333.       return code;
  334.     pop(2);
  335.     return 0;
  336. }
  337.  
  338. /* - .currentfilladjust2 <adjust.x> <adjust.y> */
  339. private int
  340. zcurrentfilladjust2(register os_ptr op)
  341. {    gs_point adjust;
  342.  
  343.     push(2);
  344.     gs_currentfilladjust(igs, &adjust);
  345.     make_real(op - 1, adjust.x);
  346.     make_real(op, adjust.y);
  347.     return 0;
  348. }
  349.  
  350. /* <bool> .setdashadapt - */
  351. private int
  352. zsetdashadapt(register os_ptr op)
  353. {    check_type(*op, t_boolean);
  354.     gs_setdashadapt(igs, op->value.boolval);
  355.     pop(1);
  356.     return 0;
  357. }
  358.  
  359. /* - .currentdashadapt <bool> */
  360. private int
  361. zcurrentdashadapt(register os_ptr op)
  362. {    push(1);
  363.     make_bool(op, gs_currentdashadapt(igs));
  364.     return 0;
  365. }
  366.  
  367. /* <num> <bool> .setdotlength - */
  368. private int
  369. zsetdotlength(register os_ptr op)
  370. {    double length;
  371.     int code = real_param(op - 1, &length);
  372.  
  373.     if ( code < 0 )
  374.       return code;
  375.     check_type(*op, t_boolean);
  376.     code = gs_setdotlength(igs, length, op->value.boolval);
  377.     if ( code < 0 )
  378.       return code;
  379.     pop(2);
  380.     return 0;
  381. }
  382.  
  383. /* - .currentdotlength <num> <bool> */
  384. private int
  385. zcurrentdotlength(register os_ptr op)
  386. {    push(2);
  387.     make_real(op - 1, gs_currentdotlength(igs));
  388.     make_bool(op, gs_currentdotlength_absolute(igs));
  389.     return 0;
  390. }
  391.  
  392. /* ------ Initialization procedure ------ */
  393.  
  394. BEGIN_OP_DEFS(zgstate_op_defs) {
  395.     {"0.currentaccuratecurves", zcurrentaccuratecurves},
  396.     {"0currentdash", zcurrentdash},
  397.     {"0.currentdashadapt", zcurrentdashadapt},
  398.     {"0.currentdotlength", zcurrentdotlength},
  399.     {"0.currentfilladjust2", zcurrentfilladjust2},
  400.     {"0currentflat", zcurrentflat},
  401.     {"0currentlinecap", zcurrentlinecap},
  402.     {"0currentlinejoin", zcurrentlinejoin},
  403.     {"0currentlinewidth", zcurrentlinewidth},
  404.     {"0currentmiterlimit", zcurrentmiterlimit},
  405.     {"0grestore", zgrestore},
  406.     {"0grestoreall", zgrestoreall},
  407.     {"0gsave", zgsave},
  408.     {"0initgraphics", zinitgraphics},
  409.     {"1.setaccuratecurves", zsetaccuratecurves},
  410.     {"2setdash", zsetdash},
  411.     {"1.setdashadapt", zsetdashadapt},
  412.     {"2.setdotlength", zsetdotlength},
  413.     {"2.setfilladjust2", zsetfilladjust2},
  414.     {"1setflat", zsetflat},
  415.     {"1.setlinecap", zsetlinecap},
  416.     {"1.setlinejoin", zsetlinejoin},
  417.     {"1setlinewidth", zsetlinewidth},
  418.     {"1setmiterlimit", zsetmiterlimit},
  419. END_OP_DEFS(0) }
  420.  
  421. /* ------ Internal routines ------ */
  422.  
  423. /* Allocate the interpreter's part of a graphics state. */
  424. private void *
  425. gs_istate_alloc(gs_memory_t *mem)
  426. {    return gs_alloc_struct(mem, int_gstate, &st_int_gstate, "int_gsave");
  427. }
  428.  
  429. /* Copy the interpreter's part of a graphics state. */
  430. private int
  431. gs_istate_copy(void *to, const void *from)
  432. {    *(int_gstate *)to = *(const int_gstate *)from;
  433.     return 0;
  434. }
  435.  
  436. /* Free the interpreter's part of a graphics state. */
  437. private void
  438. gs_istate_free(void *old, gs_memory_t *mem)
  439. {    gs_free_object(mem, old, "int_grestore");
  440. }
  441.  
  442. /* Get a numeric parameter */
  443. private int near
  444. num_param(const_os_ptr op, int (*pproc)(P2(gs_state *, floatp)))
  445. {    double param;
  446.     int code = real_param(op, ¶m);
  447.  
  448.     if ( code < 0 )
  449.       return_op_typecheck(op);
  450.     code = (*pproc)(igs, param);
  451.     if ( !code ) pop(1);
  452.     return code;
  453. }
  454.